package com.bn.feeds.tools;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import atg.core.util.StringUtils;
import atg.nucleus.ServiceMap;
import atg.repository.MutableRepository;
import atg.repository.MutableRepositoryItem;
import atg.repository.Query;
import atg.repository.QueryBuilder;
import atg.repository.QueryExpression;
import atg.repository.Repository;
import atg.repository.RepositoryException;
import atg.repository.RepositoryItem;
import atg.repository.RepositoryView;

import com.bn.feedMaster.FeedProcessException;
import com.bn.feeds.MasterFeedConfiguration;

/**
 * The Class ProductRepositoryTools.
 *
 * @author Parveen
 */
public class ProductRepositoryTools extends BaseRepositoryTools {

    /** The item descriptor name. */
    private String itemDescriptorName;

    /** The sku item descriptor name. */
    private String skuItemDescriptorName;

    /** Child skus property name **/
    private String childSkuPropertyname;
    
    /** The product item type map. */
	private Map<String, String> productItemTypeMap;

    /** The Constant GENDER. */
    private final static String GENDER = "gender";
    /** The Constant AGE_GROUP. */
    private final static String AGE_GROUP = "ageGroup";

    /** The Constant TYPE_NEW. */
    private final static String TYPE_NEW = "type_new";

    /** The Constant ADULT. */
    private final static String ADULT = "ADULT";

    /** The Constant KIDS. */
    private final static String KIDS = "KIDS";

    /** The Constant DEFAULT. */
    private final static String DEFAULT = "DEFAULT";

    /** The Constant CLOTHING. */
    private final static String CLOTHING = "CLOTHING";

    /** The Constant SHOE. */
    private final static String SHOE = "SHOE";

    /** The Constant ACCESSORY. */
    private final static String ACCESSORY = "ACCESSORY";

    /** The Constant GIFT_CARD. */
    private final static String GIFT_CARD = "GIFT CARD";

    /** The Constant EGIFT_CARD. */
    private final static String EGIFT_CARD = "EGIFT CARD";

    /** The Constant GIFT_WRAP. */
    private final static String GIFT_WRAP = "GIFT WRAP";

    /** The Constant GIFT_WRAP. */
    private final static String EPP = "EPP";

    /** The Constant GIFT_WRAP. */
    private final static String CALLING_CARD = "CALLING CARD";

    /** The Constant TARGET_GENDER. */
    private final static String TARGET_GENDER = "targetGender";

    /** The Constant MALE_GENDER. */
    private final static String MALE_GENDER = "MALE";

    /** The Constant FEMALE_GENDER. */
    private final static String FEMALE_GENDER = "FEMALE";

    /** The Constant OTHER_GENDER. */
    private final static String OTHER_GENDER = "UNISEX";
    
    private ServiceMap subTypeRepositoryToolsMap;
    
    private String subTypeDefinationProperty;
    
    private String productTemplate;
    
    private RepositoryItem mediaItem;

    /**
     * Adds/updates a repository item with the data provided
     *
     * @param config
     *            configuration for the Feed
     * @param itemList
     *            one Row data
     * @param header
     *            the feed file header
     * @param idColumnIndex
     *            index of id column property in data row(itemList)
     * @param repositoryPropertiesToTokenIndexMap
     *            a map which contains repository properties(primitive type)
     *            index in data row(which property has value at what index in
     *            data row)
     * @param repositoryItemPropertiesToTokenIndexMap
     *            a map which contains repository properties(RepositoryItem
     *            type) index in data row(which property has value at what index
     *            in data row)
     * @param productProcessedMap
     *            a map which contains id's of all the items which are processed
     *            so far in the feed execution
     * @return
     * @throws FeedProcessException
     *             the feed process exception
     */
    public List<String> processRecord(MasterFeedConfiguration config, String[] dataRow, String[] header, int idColumnIndex, Map<String, Integer> repositoryPropertiesToTokenIndexMap, Map<String, Integer> repositoryItemPropertiesToTokenIndexMap,
            Map<String, String> productProcessedMap, Map<String, Integer> mandatoryPropertiesMap) throws FeedProcessException {
        if (isLoggingDebug()) {
            logDebug("ProductRepositoryTools::>processRecord()::BEGIN");
        }
        List<String> errorList = new ArrayList<String>();
        if(!validateMandatoryProperties(config, mandatoryPropertiesMap, dataRow, errorList)){
            return errorList;
            }
        MutableRepository mutableRespository = config.getRepository();
        Repository repository = config.getPrdRepository();
        String itemId = dataRow[idColumnIndex];
        if (!StringUtils.isBlank(itemId)) {
            try {
                itemId = itemId.trim();
                RepositoryItem productItem = null;
                MutableRepositoryItem mutableProductItem = null;
                /*Integer typeIndex = repositoryPropertiesToTokenIndexMap.get(getSubTypeDefinationProperty());*/
                String itemDescriptorName = "product";
                String type = null;

                /*if (typeIndex != null) {
                    type = dataRow[typeIndex].trim().toLowerCase();
                }*/

                if (isLoggingDebug()) {
                    logDebug("ProductRepositoryTools::>processRecord()::Product Type in feed  :: " + itemDescriptorName);
                }
                
                //startTime = System.currentTimeMillis();
                RepositoryView view = repository.getView(itemDescriptorName);
    			QueryBuilder queryBuilder = view.getQueryBuilder();
                QueryExpression customerIdExpression = queryBuilder.createPropertyQueryExpression("id");
				QueryExpression custIdExpression = queryBuilder.createConstantQueryExpression(itemId);
				Query userQuery = queryBuilder.createComparisonQuery(customerIdExpression, custIdExpression, QueryBuilder.EQUALS);
				RepositoryItem[] products = view.executeQuery(userQuery);
				if(products!=null){
					productItem = products[0];
				}
				
                if (productItem != null) {
                    if (isLoggingDebug()) {
                        logDebug("ProductRepositoryTools::>processRecord()::Product item with id:" + productItem.getRepositoryId() + " already Exists. Updating Item");
                    }
                    mutableProductItem = mutableRespository.getItemForUpdate(itemId, itemDescriptorName);
                    setPropertiesToItem(mutableRespository, repository, mutableProductItem, repositoryPropertiesToTokenIndexMap, repositoryItemPropertiesToTokenIndexMap, dataRow, itemDescriptorName, errorList);
                    mutableRespository.updateItem(mutableProductItem);
                } else {
                    if (isLoggingDebug()) {
                        logDebug("ProductRepositoryTools::>processRecord()::Product item with id:" + itemId + " does not Exists. Creating new Item");
                    }
                    mutableProductItem = mutableRespository.createItem(itemId, itemDescriptorName);
                    setPropertiesToItem(mutableRespository, repository, mutableProductItem, repositoryPropertiesToTokenIndexMap, repositoryItemPropertiesToTokenIndexMap, dataRow, itemDescriptorName, errorList);
                	//RepositoryItem template = mutableRespository.getItem(getProductTemplate(),"media");
                    RepositoryItem template = getMediaItem();
                	
                	if(null!=template){
                		mutableProductItem.setPropertyValue("template", template);
                	}
                    mutableRespository.addItem(mutableProductItem);
                }
            } catch (RepositoryException e) {
            	logError(e);
                throw new FeedProcessException(e);
            } catch (NumberFormatException e) {
            	logError(e);
                throw new FeedProcessException(e);
            }
        } else {

            if (isLoggingDebug()) {
                logDebug("ProductRepositoryTools::>processRecord()::Value of Id property in feed is null");
            }
            throw new FeedProcessException("Value of Id property in feed is null");

        }
        if (isLoggingDebug()) {
            logDebug("ProductRepositoryTools::>processRecord()::END");
        }
        return errorList;
    }

    /**
     * Sets the properties to item.
     *
     * @param mutableRespository
     *            the repository
     * @param item
     *            the item
     * @param repositoryPropertiesToTokenIndexMap
     *            the repository properties to token index map
     * @param repositoryItemPropertiesToTokenIndexMap
     *            the repository item properties to token index map
     * @param dataRow
     *            the data row
     * @param itemDescriptorName
     *            the item descriptor name
     * @throws FeedProcessException
     *             the feed process exception
     */
    protected void setPropertiesToItem(MutableRepository mutableRespository, Repository repository, MutableRepositoryItem item, Map<String, Integer> repositoryPropertiesToTokenIndexMap, Map<String, Integer> repositoryItemPropertiesToTokenIndexMap,
            String[] dataRow, String itemDescriptorName, List<String> errorList) throws FeedProcessException {
        if (isLoggingDebug()) {
            logDebug("ProductRepositoryTools::>processRecord()::>setPropertiesToItem()::Begin for type: " +itemDescriptorName);
        }
        super.setPropertiesToItem(mutableRespository, repository, item, repositoryPropertiesToTokenIndexMap, repositoryItemPropertiesToTokenIndexMap, dataRow, itemDescriptorName, errorList);
        setEnumeratedProperties(item, repositoryPropertiesToTokenIndexMap, dataRow);
        if (isLoggingDebug()) {
            logDebug("ProductRepositoryTools::>processRecord()::>setPropertiesToItem()::End");
        }
    }

    /**
     * Sets the enumerated properties.
     *
     * @param item
     *            the item
     * @param repositoryPropertiesToTokenIndexMap
     *            the repository properties to token index map
     * @param dataRow
     *            the data row
     */
    private void setEnumeratedProperties(MutableRepositoryItem item, Map<String, Integer> repositoryPropertiesToTokenIndexMap, String[] dataRow) {
        if (isLoggingDebug()) {
            logDebug("ProductRepositoryTools::>processRecord()::>setPropertiesToItem()::>setEnumeratedProperties()::Begin");
        }
        if (repositoryPropertiesToTokenIndexMap.get(GENDER) != null) {
            String gender = dataRow[repositoryPropertiesToTokenIndexMap.get(GENDER)];
            if (!StringUtils.isBlank(gender)) {
            	gender = gender.toUpperCase();
                if (gender.equalsIgnoreCase(MALE_GENDER) || gender.equalsIgnoreCase(FEMALE_GENDER)) {
                    item.setPropertyValue(GENDER, gender);
                } else {
                    item.setPropertyValue(GENDER, OTHER_GENDER);
                }
            }
        }

        if (repositoryPropertiesToTokenIndexMap.get(AGE_GROUP) != null) {
            String ageGroup = dataRow[repositoryPropertiesToTokenIndexMap.get(AGE_GROUP)];
            if (!StringUtils.isBlank(ageGroup)) {
            	ageGroup = ageGroup.toUpperCase();
                if (ageGroup.equalsIgnoreCase(ADULT) || ageGroup.equalsIgnoreCase(KIDS)) {
                    item.setPropertyValue(AGE_GROUP, ageGroup);
                }
            }

        }

        if (repositoryPropertiesToTokenIndexMap.get(TYPE_NEW) != null) {
            String typeNew = dataRow[repositoryPropertiesToTokenIndexMap.get(TYPE_NEW)];

            if (isLoggingDebug()) {
                logDebug("ProductRepositoryTools::>processRecord()::>setPropertiesToItem()::>setEnumeratedProperties()::End :"
                        + " repositoryPropertiesToTokenIndexMap.get(TYPE_NEW) :"+repositoryPropertiesToTokenIndexMap.get(TYPE_NEW));
            }

            if (!StringUtils.isBlank(typeNew)) {
            	typeNew = typeNew.toUpperCase();
				int valueDEFAULT = 0;
				int valueCLOTHING = 1;
				int valueSHOE = 2;
				int valueACCESSORY = 3;
				int valueGIFT_CARD = 4;
				int valueEGIFT_CARD = 5;
				int valueGIFT_WRAP = 6;
				int valueEPP = 7;
				int valueCALLING_CARD = 8;

                if (typeNew.equalsIgnoreCase(DEFAULT)) {
                    item.setPropertyValue(TYPE_NEW, valueDEFAULT);
                }
                else if (typeNew.equalsIgnoreCase(CLOTHING)) {
                    item.setPropertyValue(TYPE_NEW, valueCLOTHING);
                }
                else if (typeNew.equalsIgnoreCase(SHOE)) {
                    item.setPropertyValue(TYPE_NEW, valueSHOE);
                }
                else if (typeNew.equalsIgnoreCase(ACCESSORY)) {
                    item.setPropertyValue(TYPE_NEW, valueACCESSORY);
                }
                else if (typeNew.equalsIgnoreCase(GIFT_CARD)) {
                    item.setPropertyValue(TYPE_NEW, valueGIFT_CARD);
                }
                else if (typeNew.equalsIgnoreCase(EGIFT_CARD)) {
                    item.setPropertyValue(TYPE_NEW, valueEGIFT_CARD);
                }
                else if (typeNew.equalsIgnoreCase(GIFT_WRAP)) {
                    item.setPropertyValue(TYPE_NEW, valueGIFT_WRAP);
                }else if (typeNew.equalsIgnoreCase(EPP)) {
                    item.setPropertyValue(TYPE_NEW, valueEPP);
                }else if (typeNew.equalsIgnoreCase(CALLING_CARD)) {
                    item.setPropertyValue(TYPE_NEW, valueCALLING_CARD);
                }

            }

        }
        if (isLoggingDebug()) {
            logDebug("ProductRepositoryTools::>processRecord()::>setPropertiesToItem()::>setEnumeratedProperties()::End");
        }

    }

    /**
     * Sets the item type single properties.
     *
     * @param mutableRepository
     *            the repository
     * @param item
     *            the item
     * @param repositoryItemPropertiesToTokenIndexMap
     *            the repository item properties to token index map
     * @param dataRow
     *            the data row
     * @throws FeedProcessException
     *             the feed process exception
     */
    private void setItemTypeSingleProperties(MutableRepository mutableRepository, Repository repository, MutableRepositoryItem item, Map<String, Integer> repositoryItemPropertiesToTokenIndexMap, String[] dataRow, List<String> errorList)
            throws FeedProcessException {
        for (Map.Entry<String, String> entry : getItemTypeSinglePropertiesMap().entrySet()) {
            if (repositoryItemPropertiesToTokenIndexMap.get(entry.getKey()) != null) {
                setItemTypeProperty(mutableRepository, repository, item, dataRow[repositoryItemPropertiesToTokenIndexMap.get(entry.getKey())], entry.getValue(), entry.getKey(), errorList);
            }
        }
    }


    /**
     * Sets the item type list properties.
     *
     * @param mutableRepository
     *            the repository
     * @param item
     *            the item
     * @param repositoryItemPropertiesToTokenIndexMap
     *            the repository item properties to token index map
     * @param dataRow
     *            the data row
     * @throws FeedProcessException
     *             the feed process exception
     */
    /*private void setItemTypeListProperties(MutableRepository mutableRepository, Repository repository, MutableRepositoryItem item, Map<String, Integer> repositoryItemPropertiesToTokenIndexMap, String[] dataRow, List<String> erroList)
            throws FeedProcessException {
        for (Map.Entry<String, String> entry : getItemTypeListPropertiesMap().entrySet()) {
            if (repositoryItemPropertiesToTokenIndexMap.get(entry.getKey()) != null) {
                setItemTypeProperties(mutableRepository, repository, item, dataRow[repositoryItemPropertiesToTokenIndexMap.get(entry.getKey())], entry.getValue(), entry.getKey(), erroList);
            }
        }
    }*/

    

    /**
     * Gets the item descriptor name.
     *
     * @return the item descriptor name
     */
    public String getItemDescriptorName() {
        return itemDescriptorName;
    }

    /**
     * Sets the item descriptor name.
     *
     * @param itemDescriptorName
     *            the new item descriptor name
     */
    public void setItemDescriptorName(String itemDescriptorName) {
        this.itemDescriptorName = itemDescriptorName;
    }

    /**
     * Gets the sku item descriptor name.
     *
     * @return the sku item descriptor name
     */
    public String getSkuItemDescriptorName() {
        return skuItemDescriptorName;
    }

    /**
     * Sets the sku item descriptor name.
     *
     * @param skuItemDescriptorName
     *            the new sku item descriptor name
     */
    public void setSkuItemDescriptorName(String skuItemDescriptorName) {
        this.skuItemDescriptorName = skuItemDescriptorName;
    }

    /**
     * Gets the product item type map.
     *
     * @return the product item type map
     */
    public Map<String, String> getProductItemTypeMap() {
        return productItemTypeMap;
    }

    /**
     * Sets the product item type map.
     *
     * @param productItemTypeMap
     *            the product item type map
     */
    public void setProductItemTypeMap(Map<String, String> productItemTypeMap) {
        this.productItemTypeMap = productItemTypeMap;
    }


    /**
     * Gets the wine item type single properties map.
     *
     * @return the wine item type single properties map
     */
    /*public Map<String, String> getWineItemTypeSinglePropertiesMap() {
        return wineItemTypeSinglePropertiesMap;
    }*/

    /**
     * Sets the wine item type single properties map.
     *
     * @param wineItemTypeSinglePropertiesMap
     *            the wine item type single properties map
     */
   /* public void setWineItemTypeSinglePropertiesMap(Map<String, String> wineItemTypeSinglePropertiesMap) {
        this.wineItemTypeSinglePropertiesMap = wineItemTypeSinglePropertiesMap;
    }*/

    /**
     * Gets the wine string properties.
     *
     * @return the wine string properties
     */
    /*public List<String> getWineStringProperties() {
        return wineStringProperties;
    }*/

    /**
     * @return the truConfiguration
     */
    /*
     * public HEBConfigurations getHebConfiguration() { return truConfiguration;
     * }
     */

    /**
     * @param truConfiguration
     *            the truConfiguration to set
     */
    /*
     * public void setHebConfiguration(HEBConfigurations truConfiguration) {
     * this.truConfiguration = truConfiguration; }
     */

    /**
     * Sets the wine string properties.
     *
     * @param wineStringProperties
     *            the new wine string properties
     */
   /* public void setWineStringProperties(List<String> wineStringProperties) {
        this.wineStringProperties = wineStringProperties;
    }*/

    /**
     * @return the pickerTypeItemDescriptorName
     */
    /*public String getPickerTypeItemDescriptorName() {
        return pickerTypeItemDescriptorName;
    }

    *//**
     * @param pickerTypeItemDescriptorName
     *            the pickerTypeItemDescriptorName to set
     *//*
    public void setPickerTypeItemDescriptorName(String pickerTypeItemDescriptorName) {
        this.pickerTypeItemDescriptorName = pickerTypeItemDescriptorName;
    }*/

    /**
     * @return the productTypeToSkuTypeMap
     */
    /*public Map<String, String> getProductTypeToSkuTypeMap() {
        return productTypeToSkuTypeMap;
    }*/

    /**
     * @param productTypeToSkuTypeMap
     *            the productTypeToSkuTypeMap to set
     */
    /*public void setProductTypeToSkuTypeMap(Map<String, String> productTypeToSkuTypeMap) {
        this.productTypeToSkuTypeMap = productTypeToSkuTypeMap;
    }*/

    /*
     * (non-Javadoc)
     *
     * @see com.tru.feeds.tools.BaseRepositoryTools#cleanUpData(atg.repository.
     * MutableRepository, java.lang.String)
     */
    @Override
    public boolean cleanUpData(MutableRepository repository, String itemDescriptor) throws FeedProcessException {
        // TODO Auto-generated method stub
        return false;
    }
    /**
     * @return the wineIntProperties
     */
    /*public List<String> getWineIntProperties() {
        return wineIntProperties;
    }*/

    /**
     * @param wineIntProperties
     *            the wineIntProperties to set
     */
   /* public void setWineIntProperties(List<String> wineIntProperties) {
        this.wineIntProperties = wineIntProperties;
    }*/

    /**
     * @return the addonProductParentPropertyName
     */
   /* public String getAddonProductParentPropertyName() {
        return addonProductParentPropertyName;
    }*/

    /**
     * @param addonProductParentPropertyName
     *            the addonProductParentPropertyName to set
     */
    /*public void setAddonProductParentPropertyName(String addonProductParentPropertyName) {
        this.addonProductParentPropertyName = addonProductParentPropertyName;
    }*/

    /**
     * @return the isAddOnProductPropertyName
     */
    /*public String getIsAddOnProductPropertyName() {
        return isAddOnProductPropertyName;
    }*/

    /**
     * @param isAddOnProductPropertyName
     *            the isAddOnProductPropertyName to set
     */
    /*public void setIsAddOnProductPropertyName(String isAddOnProductPropertyName) {
        this.isAddOnProductPropertyName = isAddOnProductPropertyName;
    }*/

    /**
     * @return the showOnSitePropertyName
     */
    /*public String getShowOnSitePropertyName() {
        return showOnSitePropertyName;
    }

    *//**
     * @param showOnSitePropertyName
     *            the showOnSitePropertyName to set
     *//*
    public void setShowOnSitePropertyName(String showOnSitePropertyName) {
        this.showOnSitePropertyName = showOnSitePropertyName;
    }*/

    /**
     * @return the addOnProductsPropertyName
     */
    /*public String getAddOnProductsPropertyName() {
        return addOnProductsPropertyName;
    }*/

    /**
     * @param addOnProductsPropertyName
     *            the addOnProductsPropertyName to set
     */
    /*public void setAddOnProductsPropertyName(String addOnProductsPropertyName) {
        this.addOnProductsPropertyName = addOnProductsPropertyName;
    }*/

    /**
     * @return the wineDoubleProperties
     */
   /* public List<String> getWineDoubleProperties() {
        return wineDoubleProperties;
    }*/

    /**
     * @param wineDoubleProperties
     *            the wineDoubleProperties to set
     */
   /* public void setWineDoubleProperties(List<String> wineDoubleProperties) {
        this.wineDoubleProperties = wineDoubleProperties;
    }*/

    /**
     * @return the skuShowOnSitePropertyName
     */
    /*public String getSkuShowOnSitePropertyName() {
        return skuShowOnSitePropertyName;
    }*/

    /**
     * @param skuShowOnSitePropertyName
     *            the skuShowOnSitePropertyName to set
     */
    /*public void setSkuShowOnSitePropertyName(String skuShowOnSitePropertyName) {
        this.skuShowOnSitePropertyName = skuShowOnSitePropertyName;
    }*/

    /**
     * @return the categoryProperty
     */
    /*public String getCategoryProperty() {
        return categoryProperty;
    }*/

    /**
     * @param categoryProperty
     *            the categoryProperty to set
     */
    /*public void setCategoryProperty(String categoryProperty) {
        this.categoryProperty = categoryProperty;
    }*/

    /**
     * @return the productPickersMappingsMap
     */
    /*public Map<String, PickerTypeMapping> getProductPickersMappingsMap() {
        if (productPickersMappingsMap == null) {
            productPickersMappingsMap = new HashMap<String, PickerTypeMapping>();
        }
        return productPickersMappingsMap;
    }*/

    /**
     * @return the childSkuPropertyname
     */
    public String getChildSkuPropertyname() {
        return childSkuPropertyname;
    }

    /**
     * @param childSkuPropertyname
     *            the childSkuPropertyname to set
     */
    public void setChildSkuPropertyname(String childSkuPropertyname) {
        this.childSkuPropertyname = childSkuPropertyname;
    }

    public ServiceMap getSubTypeRepositoryToolsMap() {
		return subTypeRepositoryToolsMap;
	}

    public void setSubTypeRepositoryToolsMap(ServiceMap subTypeRepositoryToolsMap) {
		this.subTypeRepositoryToolsMap = subTypeRepositoryToolsMap;
	}

    public String getSubTypeDefinationProperty() {
		return subTypeDefinationProperty;
	}

    public void setSubTypeDefinationProperty(String subTypeFeedHeaderName) {
		this.subTypeDefinationProperty = subTypeFeedHeaderName;
	}

	public String getProductTemplate() {
		return productTemplate;
	}

	public void setProductTemplate(String productTemplate) {
		this.productTemplate = productTemplate;
	}

	public RepositoryItem getMediaItem() {
		return mediaItem;
	}

	public void setMediaItem(RepositoryItem mediaItem) {
		this.mediaItem = mediaItem;
	}

}
